package org.fireking.myapplication

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import com.github.mikephil.charting.animation.ChartAnimator
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider
import com.github.mikephil.charting.renderer.LineChartRenderer
import com.github.mikephil.charting.utils.Transformer
import com.github.mikephil.charting.utils.ViewPortHandler
import org.fireking.myapplication.drawing.Shape
import org.fireking.myapplication.drawing.impl.CurveDrawingStrategy
import org.fireking.myapplication.drawing.impl.LineDrawingStrategy
import org.fireking.myapplication.drawing.impl.RectangleDrawingStrategy
import kotlin.math.abs

/**
 * 自定义图表渲染器，用于在LineChart上绘制各种图形
 * 通过继承LineChartRenderer，确保绘制的图形能够随图表一起滚动和缩放
 * 使用策略模式实现不同图形的绘制和交互
 */
class ChartDrawingRenderer(
    chart: LineDataProvider, animator: ChartAnimator, viewPortHandler: ViewPortHandler
) : LineChartRenderer(chart, animator, viewPortHandler) {

    // 绘制用的画笔
    private val paint = Paint().apply {
        color = Color.RED
        strokeWidth = 2f
        style = Paint.Style.STROKE
        isAntiAlias = true
    }

    // 控制点画笔
    private val controlPointPaint = Paint().apply {
        color = Color.BLUE
        strokeWidth = 2f
        style = Paint.Style.FILL
        isAntiAlias = true
    }

    // 选中状态画笔
    private val selectedPaint = Paint().apply {
        color = Color.BLUE
        strokeWidth = 2f
        style = Paint.Style.STROKE
        isAntiAlias = true
        pathEffect = android.graphics.DashPathEffect(floatArrayOf(10f, 5f), 0f)
    }

    // 已完成的图形列表
    private val shapes = mutableListOf<Shape>()

    // 当前选中的图形
    private var selectedShape: Shape? = null

    // 当前选中的控制点
    private var selectedControlPoint: ControlPoint? = null

    // 当前是否为编辑模式
    private var isEditMode = false

    // 选择图形时的动画效果相关变量
    private var selectionAnimationProgress = 0f
    private var selectionAnimationStartTime = 0L
    private var isAnimatingSelection = false
    private val SELECTION_ANIMATION_DURATION = 300L  // 300毫秒动画

    // 在类的顶部添加以下变量
    private var lastClickedShape: Shape? = null

    // 图形工厂用于创建新图形
    private val shapeFactory = ShapeFactory()

    /**
     * 将选中的图形移到顶层（最后显示，最上面）
     */
    fun bringSelectedShapeToFront() {
        val shape = selectedShape ?: return

        if (shapes.remove(shape)) {
            shapes.add(shape)  // 添加到列表末尾，使其绘制在最上层
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
        }
    }

    /**
     * 将选中的图形移到底层（最先显示，最下面）
     */
    fun sendSelectedShapeToBack() {
        val shape = selectedShape ?: return

        if (shapes.remove(shape)) {
            shapes.add(0, shape)  // 添加到列表开头，使其绘制在最底层
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
        }
    }

    /**
     * 设置编辑模式
     */
    fun setEditMode(editMode: Boolean) {
        isEditMode = editMode
        if (!editMode) {
            // 退出编辑模式时取消选择
            selectedShape = null
            selectedControlPoint = null
        }
        (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
    }

    /**
     * 是否处于编辑模式
     */
    fun isInEditMode(): Boolean = isEditMode

    /**
     * 处理触摸事件：选择、移动图形
     * 返回是否处理了事件
     */
    fun handleEditModeTouch(x: Float, y: Float, action: Int): Boolean {
        if (!isEditMode) return false

        // 转换为图表值坐标
        val transformer =
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.getTransformer(
                com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT
            ) ?: return false

        val pixelPointsPx = floatArrayOf(x, y)
        transformer.pixelsToValue(pixelPointsPx)
        val chartX = pixelPointsPx[0]
        val chartY = pixelPointsPx[1]

        return when (action) {
            android.view.MotionEvent.ACTION_DOWN -> handleTouchDown(chartX, chartY)
            android.view.MotionEvent.ACTION_MOVE -> handleTouchMove(chartX, chartY)
            android.view.MotionEvent.ACTION_UP, android.view.MotionEvent.ACTION_CANCEL -> handleTouchUp()

            else -> false
        }
    }

    private var lastTouchX = 0f
    private var lastTouchY = 0f
    private var isDragging = false

    private fun handleTouchDown(chartX: Float, chartY: Float): Boolean {
        lastTouchX = chartX
        lastTouchY = chartY
        isDragging = false
        selectedControlPoint = null  // 重置控制点选择

        // 首先处理图形选择（从最上层开始检查）
        val shapesInRenderOrder = shapes.reversed()
        val clickedShapes = shapesInRenderOrder.filter { it.containsPoint(chartX, chartY, 0F) }

        if (clickedShapes.isNotEmpty()) {
            // 选择图形
            val newSelectedShape =
                if (selectedShape != null && clickedShapes.contains(selectedShape)) {
                    // 获取开始判断控制点时使用的原有图形，因为后面可能会将selectedShape设为null
                    val originalSelectedShape = selectedShape
                    // 单击已选中图形，优先检查控制点，不再自动设置拖动模式
                    isDragging = false
                    // 仅在编辑模式下检查控制点
                    if (isEditMode) {
                        // 查找是否点击了控制点
                        val controlPoints = originalSelectedShape!!.getControlPoints()
                        val controlPoint = controlPoints.firstOrNull {
                            isPointNearPoint(chartX, chartY, it.x, it.y, 30F) // 缩小控制点选择范围
                        }
                        if (controlPoint != null) {
                            // 选中了控制点
                            selectedControlPoint = controlPoint
                        }
                        isDragging = true
                    }
                    // 记录此次点击
                    lastClickedShape = originalSelectedShape
                    originalSelectedShape
                } else {
                    // 选择新图形
                    val shapeToSelect = clickedShapes.first()
                    // 更新选择状态
                    selectedShape?.isSelected = false
                    shapeToSelect.isSelected = true
                    // 修改：不再自动启用拖动模式
                    isDragging = false
                    // 开始选择动画
                    startSelectionAnimation()
                    // 记录此次点击
                    lastClickedShape = shapeToSelect
                    shapeToSelect
                }
            // 更新选中状态
            selectedShape = newSelectedShape
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
            return true
        }

        // 如果点击了空白区域，取消选择
        if (selectedShape != null) {
            selectedShape?.isSelected = false
            selectedShape = null
            selectedControlPoint = null
            isDragging = false
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
            return true
        }

        return false
    }

    private fun handleTouchMove(x: Float, y: Float): Boolean {
        if (!isDragging) {
            return false
        }

        val deltaX = x - lastTouchX
        val deltaY = y - lastTouchY

        // 忽略过小的移动，防止抖动（减小阈值，提高灵敏度）
        if (abs(deltaX) < 0.0005f && abs(deltaY) < 0.0005f) {
            return true
        }

        if (selectedControlPoint != null && selectedShape != null && isEditMode) {
            // 编辑模式下移动控制点
            selectedShape!!.applyControlPointMove(selectedControlPoint!!.id, deltaX, deltaY)
        } else if (selectedShape != null) {
            // 拖动整个图形
            selectedShape!!.move(deltaX, deltaY)
        } else {
            // 这种情况不应该发生，可能是状态错误，重置一下
            isDragging = false
        }

        lastTouchX = x
        lastTouchY = y

        (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
        return true
    }

    private fun handleTouchUp(): Boolean {
        if (isDragging) {
            isDragging = false
            selectedControlPoint = null
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
            return true
        }
        return false
    }

    private fun isPointNearPoint(
        touchX: Float, touchY: Float, pointX: Float, pointY: Float, tolerance: Float
    ): Boolean {
        val touchArray = floatArrayOf(touchX, touchY)
        getTransformer()?.pointValuesToPixel(touchArray)

        val pointArray = floatArrayOf(pointX, pointY)
        getTransformer()?.pointValuesToPixel(pointArray)

        val rectF = RectF(
            pointArray[0] - tolerance,
            pointArray[1] - tolerance,
            pointArray[0] + tolerance,
            pointArray[1] + tolerance
        )
        return rectF.contains(touchArray[0], touchArray[1])
    }

    /**
     * 清除所有绘制的图形
     */
    fun clearDrawings() {
        shapes.clear()
        (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
    }

    /**
     * 撤销上一步绘制
     */
    fun undo() {
        if (shapes.isNotEmpty()) {
            shapes.removeAt(shapes.size - 1)
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
        }
    }

    /**
     * 添加直线
     */
    fun addLine(startX: Float, startY: Float, endX: Float, endY: Float, color: Int, width: Float) {
        val transformer =
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.getTransformer(
                com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT
            ) ?: return

        // 将屏幕坐标转换为图表值坐标
        val startPointPx = floatArrayOf(startX, startY)
        val endPointPx = floatArrayOf(endX, endY)

        // 使用接受数组的方法
        transformer.pixelsToValue(startPointPx)
        transformer.pixelsToValue(endPointPx)

        // 使用工厂创建线形
        val lineShape = shapeFactory.createLine(
            startPointPx[0], startPointPx[1], endPointPx[0], endPointPx[1], color, width
        )
        shapes.add(lineShape)

        // 刷新图表
        (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
    }

    /**
     * 添加矩形
     */
    fun addRectangle(
        left: Float, top: Float, right: Float, bottom: Float, color: Int, width: Float
    ) {
        val transformer =
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.getTransformer(
                com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT
            ) ?: return

        // 将屏幕坐标转换为图表值坐标
        val leftTopPx = floatArrayOf(left, top)
        val rightBottomPx = floatArrayOf(right, bottom)

        transformer.pixelsToValue(leftTopPx)
        transformer.pixelsToValue(rightBottomPx)

        // 使用工厂创建矩形
        val rectangleShape = shapeFactory.createRectangle(
            leftTopPx[0], leftTopPx[1], rightBottomPx[0], rightBottomPx[1], color, width
        )
        shapes.add(rectangleShape)

        // 刷新图表
        (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
    }

    /**
     * 添加曲线
     */
    fun addCurve(points: List<Pair<Float, Float>>, color: Int, width: Float) {
        if (points.size < 2) return

        val transformer =
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.getTransformer(
                com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT
            ) ?: return

        // 将屏幕坐标转换为图表值坐标
        val chartPoints = points.map { (x, y) ->
            val pointPx = floatArrayOf(x, y)
            transformer.pixelsToValue(pointPx)
            Pair(pointPx[0], pointPx[1])
        }.toMutableList()  // 转换为 MutableList

        // 使用工厂创建曲线
        val curveShape = shapeFactory.createCurve(chartPoints, color, width)
        shapes.add(curveShape)

        // 刷新图表
        (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
    }

    /**
     * 开始选择动画
     */
    private fun startSelectionAnimation() {
        isAnimatingSelection = true
        selectionAnimationProgress = 0f
        selectionAnimationStartTime = System.currentTimeMillis()
        animateSelection()
    }

    /**
     * 动画选择效果
     */
    private fun animateSelection() {
        val currentTime = System.currentTimeMillis()
        val elapsed = currentTime - selectionAnimationStartTime

        if (elapsed < SELECTION_ANIMATION_DURATION) {
            selectionAnimationProgress = elapsed.toFloat() / SELECTION_ANIMATION_DURATION
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()

            // 继续动画
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.postDelayed({
                animateSelection()
            }, 16) // 约60fps
        } else {
            selectionAnimationProgress = 1f
            isAnimatingSelection = false
            (mChart as? com.github.mikephil.charting.charts.LineChart)?.invalidate()
        }
    }

    /**
     * 在图表渲染完成后，绘制自定义图形
     */
    override fun drawExtras(canvas: Canvas) {
        super.drawExtras(canvas)

        // 渲染每个图形
        for (shape in shapes) {
            // 如果图形被选中，使用选中画笔
            val shapePaint = if (shape.isSelected) {
                selectedPaint.apply {
                    color = shape.color
                    strokeWidth = shape.lineWidth

                    // 如果在动画中，调整虚线效果
                    if (isAnimatingSelection && selectedShape == shape) {
                        val phase = selectionAnimationProgress * 20
                        pathEffect = android.graphics.DashPathEffect(floatArrayOf(10f, 5f), phase)
                    } else {
                        pathEffect = android.graphics.DashPathEffect(floatArrayOf(10f, 5f), 0f)
                    }
                }
            } else {
                paint.apply {
                    color = shape.color
                    strokeWidth = shape.lineWidth
                }
            }

            // 使用绘制策略绘制图形
            shape.draw(canvas, getTransformer(), shapePaint)

            // 如果是编辑模式且图形被选中，绘制控制点
            if (isEditMode && shape.isSelected) {
                drawControlPoints(canvas, shape)

                // 在选中的图形旁添加一个小标记，表示图层顺序
                val index = shapes.indexOf(shape) + 1
                drawLayerOrderIndicator(canvas, shape, index, shapes.size)
            }
        }
    }

    /**
     * 获取图表的Transformer
     */
    private fun getTransformer(): Transformer? {
        return (mChart as? com.github.mikephil.charting.charts.LineChart)?.getTransformer(
            com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT
        )
    }

    /**
     * 绘制控制点
     */
    private fun drawControlPoints(canvas: Canvas, shape: Shape) {
        val transformer = getTransformer() ?: return

        val controlPoints = shape.getControlPoints()
        for (controlPoint in controlPoints) {
            val pointArray = floatArrayOf(controlPoint.x, controlPoint.y)
            transformer.pointValuesToPixel(pointArray)

            // 根据控制点类型设置颜色
            when (controlPoint.type) {
                ControlPointType.START, ControlPointType.END -> {
                    controlPointPaint.color = Color.GREEN
                }

                ControlPointType.LEFT, ControlPointType.TOP, ControlPointType.RIGHT, ControlPointType.BOTTOM -> {
                    controlPointPaint.color = Color.BLUE
                }

                ControlPointType.CORNER -> {
                    controlPointPaint.color = Color.RED
                }
            }

            // 绘制控制点
            canvas.drawCircle(pointArray[0], pointArray[1], 8f, controlPointPaint)

            // 如果是当前选中的控制点，绘制一个额外的圆圈
            if (selectedControlPoint != null && selectedControlPoint!!.id == controlPoint.id && selectedShape == shape) {
                val strokePaint = Paint(controlPointPaint)
                strokePaint.style = Paint.Style.STROKE
                strokePaint.strokeWidth = 2f
                canvas.drawCircle(pointArray[0], pointArray[1], 12f, strokePaint)
            }
        }
    }

    /**
     * 绘制图层顺序指示器
     */
    private fun drawLayerOrderIndicator(canvas: Canvas, shape: Shape, index: Int, total: Int) {
        // 获取第一个控制点的位置用于绘制标记
        val controlPoints = shape.getControlPoints()
        if (controlPoints.isEmpty()) return

        val firstPoint = controlPoints[0]
        val pointArray = floatArrayOf(firstPoint.x, firstPoint.y)

        val transformer = getTransformer() ?: return
        transformer.pointValuesToPixel(pointArray)

        // 绘制一个小圆圈显示图层顺序
        val layerPaint = Paint().apply {
            color = Color.BLACK
            style = Paint.Style.FILL
            textSize = 12f
            isAntiAlias = true
        }

        // 绘制背景圆圈
        canvas.drawCircle(pointArray[0] - 25f, pointArray[1] - 25f, 15f, layerPaint)

        // 绘制文本
        layerPaint.color = Color.WHITE
        val text = "$index/$total"
        canvas.drawText(text, pointArray[0] - 32f, pointArray[1] - 20f, layerPaint)
    }

    // 控制点类型
    enum class ControlPointType {
        START, END, LEFT, TOP, RIGHT, BOTTOM, CORNER
    }

    // 控制点
    data class ControlPoint(
        val id: Int,         // 控制点ID
        val x: Float,        // 控制点X坐标
        val y: Float,        // 控制点Y坐标
        val type: ControlPointType  // 控制点类型
    )

    /**
     * 图形工厂类 - 使用策略模式创建各种类型的图形
     */
    inner class ShapeFactory {
        fun createLine(
            startX: Float, startY: Float, endX: Float, endY: Float, color: Int, width: Float
        ): Shape {
            val strategy = LineDrawingStrategy(startX, startY, endX, endY)
            return Shape(strategy, color, width)
        }

        fun createRectangle(
            left: Float, top: Float, right: Float, bottom: Float, color: Int, width: Float
        ): Shape {
            val strategy = RectangleDrawingStrategy(left, top, right, bottom)
            return Shape(strategy, color, width)
        }

        fun createCurve(points: MutableList<Pair<Float, Float>>, color: Int, width: Float): Shape {
            val strategy = CurveDrawingStrategy(points)
            return Shape(strategy, color, width)
        }
    }
}